/**
* @file Game.cpp
* Implementation of the game
* @author Timmy Nelen
* @date 18/11/2010
*/

#include "Game.h"

/**
 * Constructor for a game object
 *
 * @param[in] fact The abstractfactory to be used
 * @param[in] gen The levelgenerator to be used
 * @param[in] lives The amount of lives the player has
 * @param[in] player The player which is playing the game
 */
bo::Game::Game(AbstractFactory* fact, LevelGenerator* gen, const int fps, const int lives, Player* player)
	:fFactory(fact), fLvlGen(gen){
	this->fPlayer = player;
	this->fTimer = new Stopwatch(fps);
}

/**
 * Destructor of the game object
 */
bo::Game::~Game() {
	delete this->fFactory;
	delete this->fLvlGen;
	delete this->fTimer;
	delete this->fPlayer;
}

/**
 * Adds a level to the game
 *
 * @param[in] lev The level which is to be added to the game
 */
void bo::Game::AddLevel(Level* lev){
	this->fLevVector.push_back(lev);
}

/**
 * Generates a standard level with the given sprites
 *
 * @param[in] paddleFile The filename of the paddle sprite
 * @param[in] breakableFile The filename of the breakable sprite
 * @param[in] ballFile The filename of the ball sprite
 */
void bo::Game::GenStdGame(const char* paddleFile, const char* breakableFile, const char* ballFile,
		const char* powFile, const char* powerUpFile){
	this->AddLevel(this->fLvlGen->CreateStandardLevel(breakableFile, paddleFile, ballFile, powFile, powerUpFile));
}

/**
 * Runs the game, breaks out of the loop & exits the function when needed
 */
void bo::Game::Run(int& returnValue){
	enum Gamestate{NEXTLEVEL, GAMEOVER, QUIT, CONTINUE};
	this->fGameRunning = true;
	bool gameOver = false;
	int levelReturn = 0;
	while ( this->fGameRunning && !gameOver ){
		for (vector<Level*>::iterator it = this->fLevVector.begin(); it!=this->fLevVector.end(); ++it) {
			this->fGameRunning = true;
			while (this->fGameRunning){
				(*it)->AdvanceLevelState(levelReturn, this->fPlayer);
				switch(levelReturn){
				case NEXTLEVEL:
					// Set fGameRunning to false so we break out of the current level loop and we can advance
					this->fGameRunning = false;
					break;
				case GAMEOVER:
					gameOver = true;
					returnValue = 1;
					return ;
				case QUIT:
					return;
				case CONTINUE:
					break;
				}
				this->fTimer->GetTick();
				(*it)->Visualize();
				this->fPlayer->Visualize();
			}
		}
	}
	return;
}
